package han.cirno.corrupt.funny

import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import java.util.concurrent.atomic.AtomicBoolean

@Suppress("unused")
abstract class BaseSurface:SurfaceView,SurfaceHolder.Callback,Runnable {
    companion object{
        val hasInstance=AtomicBoolean(false)
        private var canvas: Canvas?=null
    }

    @Volatile
    protected var canvasWidth:Int=0
    @Volatile
    protected var canvasHeight:Int=0
    @Volatile
    private var lastTime:Long=0
    @Volatile
    private var running=true

    constructor(context: Context?) : super(context){
        init()
    }
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs){
        init()
    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr){
        init()
    }
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes){
        init()
    }

    fun init(){
        holder.addCallback(this)
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        running=true
        while (hasInstance.get()){
            Log.d("Corrupt","Busy wait")
        }
        hasInstance.set(true)
        Thread(this).start()
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        running=true
        canvasWidth=width
        canvasHeight=height
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        hasInstance.set(false)
        running=false
    }

    override fun run() {
        lastTime=System.currentTimeMillis()
        while (running){
            val now=System.currentTimeMillis()
            val deltaTime=now-lastTime
            lastTime=now
            try{
                synchronized(holder) {
                    canvas = holder.lockCanvas()
                    loop(canvas!!, deltaTime)
                }
            }catch (e:Exception){
                e.printStackTrace()
            }
            try {
                holder.unlockCanvasAndPost(canvas)
            }catch (e:Exception){
                e.printStackTrace()
                running=false
            }
        }
    }

    abstract fun loop(canvas: Canvas, deltaTimeMs:Long)
}